#include "../../include/threadPool.h"
#include "../../include/myfunc.h"

int readmd5(char *filename, char * buf){
    char cmd[128];
    sprintf(cmd, "%s %s","md5sum", filename);
    FILE *fp = popen(cmd, "r");
    if(fp == NULL)
        return -1;
    bzero(buf, 128);
    fread(buf, 1, 128, fp);
    int size = strlen(buf);
    int i = 0;
    while(i < size) {
        if(isspace(buf[i])) {
            i++;
            continue;
        }
        while(i < size && !isspace(buf[i])) {
            i++;
        }
        break;
    }
    buf[i] = '\0';
    pclose(fp);
    return 0;
}

int sendn(int netFd, void * buf, int len) {
    char *pbuf = (char *)buf;
    train_t train;
    bzero(&train,sizeof(train));
    train.length = len;    
    strcpy(train.buf, buf);
    int ret = send(netFd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
    return 0;
}

int recvn(int sockFd,void *pstart,int len){
    int total = 0;
    int ret;
    char *p = (char *)pstart;
    while(total < len){
        ret = recv(sockFd,p+total,len-total,0);
        total += ret;
        if(ret == -1 || ret == 0)
            return -1;
    }
    return 0;
}

int msgprocess(int netFd, train_t * train) {
    int ret = recvn(netFd, &train->length, sizeof(int));
    THREAD_ERROR_CHECK(ret, "recv");
    
    ret = recvn(netFd, &train->buf, train->length);   
    THREAD_ERROR_CHECK(ret, "recv");
    
    return 0;
}

int recvFile(int netFd, char *filename) {
    int dataLength;
    int ret = recv(netFd,&dataLength,sizeof(dataLength),0);
    ERROR_CHECK(ret,-1,"recv");
    ret = recv(netFd,filename,dataLength,0);
    ERROR_CHECK(ret,-1,"recv");
    int filefd = open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
    ERROR_CHECK(filefd,-1,"open");
    while (1){
        ret = recv(netFd,&dataLength,sizeof(int),0);
        ERROR_CHECK(ret,-1,"recv");
        if(dataLength != 0){
            printf("dataLength = %d\n",dataLength);
        }
        if (dataLength == 0){
            break;
        }
        train_t train;
        ret = recv(netFd,train.buf,dataLength,0);
        ERROR_CHECK(ret,-1,"recv");
        write(filefd,train.buf,ret);
    }
}

int sendFile(int netFd, char *filename) {
    int filefd = open(filename, O_RDONLY);
    
    struct stat statbuf;
    int ret = fstat(filefd, &statbuf);
    THREAD_ERROR_CHECK(ret, "fstat");
    train_t train;
    train.length = strlen(filename);
    int fileSize = statbuf.st_size;
    
    memcpy(train.buf, &fileSize, sizeof(int));
    strcat(train.buf,filename);
    ret = send(netFd, &train, train.length+sizeof(train.length), MSG_NOSIGNAL);
    THREAD_ERROR_CHECK(ret, "send");
    if (fileSize > 100*2E20){
        char *p = (char*)mmap(NULL,sizeof(train.buf)+sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,filefd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        int total = 0;
        while(total < fileSize){
            if(fileSize-total < sizeof(train.buf)){
                train.length = fileSize-total;
            }
            else{
                train.length = sizeof(train.buf);  
            }
            memcpy(train.buf,p+total,train.length);
            total += train.length;
            send(netFd,&train,train.length+sizeof(train.length),MSG_NOSIGNAL);
        }
        munmap(p,fileSize);
    }
    while(1) {
        bzero(&train, sizeof(train));
        ret = read(filefd, train.buf, sizeof(train.buf));
        if(ret == 0)
            break;
        train.length = ret;
        ret = send(netFd, &train, sizeof(train.length)+train.length, MSG_NOSIGNAL);
        THREAD_ERROR_CHECK(ret, "send");
    }
    
    train.length = 0;
    ret = send(netFd, &train, sizeof(train.length)+train.length, MSG_NOSIGNAL);
    THREAD_ERROR_CHECK(ret, "send");
    close(filefd); 
}
